package lc.q51_100;

/**
 * 给定一个整数 n，求以 1 ... n 为节点组成的二叉搜索树有多少种？
 */
public class Q96 {

    public int numTrees(int n) {
        // 二叉搜索树多少种就看left的多少种right多少种加起来
        if (n == 0) {
            return 1;
        }
        if (n == 1) {
            return 1;
        }
        int sum = 0;
        for (int i = 1; i <= n; i++) {
            // 可否改成dp，对于任意数来讲，它的个数都是
            sum += (numTrees(i-1)*numTrees(n-i));
        }
        return sum;
    }

    public int numTrees2(int n) {
        // 二叉搜索树多少种就看left的多少种right多少种加起来
        // 卡特兰数方式求解
        // 类推入栈出栈序列得公式
        if (n == 0) {
            return 1;
        }
        if (n == 1) {
            return 1;
        }
        int[] dp = new int[n+1];
        dp[0] = 1;
        dp[1] = 1;
        for (int i = 2; i <= n; i++) {
            // 将i分解成两个数
            for (int j = 0; j < i ; j++) {
                dp[i] += (dp[j] * dp[i -j -1]);
            }
        }
        return dp[n];
    }
    public int numTrees2_1(int n) {
        // 卡特兰数公式是
        // P（n+1) = (4N+2)/(N+2)*P(N)
        long num = 1;
        for (int i = 0; i < n; i++) {
            num = (4*i+2) * num / (i+2);
        }
        return (int) num;
    }

    public static void main(String[] args) {
        Q96 q96 = new Q96();
        System.out.println(q96.numTrees2_1(4));
    }
}
